package com.tbit.uqbike.service.business.operationsanalysis.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tbit.uqbike.constant.AccountDayStatConstant;
import com.tbit.uqbike.constant.Constants;
import com.tbit.uqbike.constant.enums.AccountDayStatEnum;
import com.tbit.uqbike.enums.WeatherEnum;
import com.tbit.uqbike.object.pojo.AccountDayStat;
import com.tbit.manager.api.dto.OrderStatReturnDTO;
import com.tbit.uqbike.service.business.operationsanalysis.OrderOAService;
import com.tbit.uqbike.webmanager.dao.capital.RideLogDetailsDao;
import com.tbit.uqbike.webmanager.dao.log.AccountweatherDao;
import com.tbit.uqbike.webmanager.dao.stat.AccountDayStatDao;
import com.tbit.uqbike.object.pojo.Accountweather;
import com.tbit.utils.DateTimeUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单分析Service接口实现
 *
 * @author <a href="mailto:chen.wutian@tbit.com.cn">BUGTian</a>
 * @since 2025/2/27
 */
@Service
public class OrderOAServiceImpl implements OrderOAService {

    @Autowired
    private AccountDayStatDao accountDayStatDao;
    @Autowired
    private AccountweatherDao accountweatherDao;
    @Autowired
    private RideLogDetailsDao rideLogDetailsDao;


    /**
     * @description: 获取车辆订单的统计数据（订单收益、订单量、车均收益等）
     * @author: mo.shanyong
     * @date: 2025/3/7 13:39
     * @param: accountId 区域Id
     * @param: startDate 筛选开始时间
     * @param: endDate 筛选结束时间
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    @Override
    public Map<String, Object> getOrderBaseData(Integer accountId, Date startDate, Date endDate) {
        //获取筛选周期的统计数据
        QueryWrapper<AccountDayStat> wrapper = new QueryWrapper<AccountDayStat>()
                .eq("accountId", accountId)
                .between("dataDate", DateTimeUtil.getyyyyMMddByDate(startDate), DateTimeUtil.getyyyyMMddByDate(endDate))
                .in("dataType", AccountDayStatEnum.getOrderAnalysisDataType());
        List<AccountDayStat> accountDayStatList = accountDayStatDao.selectList(wrapper);
        //获取筛选周期的上一个周期的统计数据
        List<AccountDayStat> lastAccountStatList = this.getLastCycleStat(accountId, startDate, endDate);
        if (CollectionUtils.isEmpty(accountDayStatList)){
            return getZeroData(CollectionUtils.isNotEmpty(lastAccountStatList));
        }
        Map<Integer, List<AccountDayStat>> accountDayStatMap = accountDayStatList.stream().collect(Collectors.groupingBy(AccountDayStat::getDataType));
        Map<Integer, List<AccountDayStat>> lastAccountDayStatMap = lastAccountStatList.stream().collect(Collectors.groupingBy(AccountDayStat::getDataType));
        return this.getBaseData(accountDayStatMap,lastAccountDayStatMap);
    }

    /**
     * @description: 获取订单收益折线图数据
     * @author: mo.shanyong
     * @date: 2025/3/7 13:43
     * @param: accountId 区域id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    @Override
    public List<OrderStatReturnDTO> getOrderFeeLineData(Integer accountId, Date startDate, Date endDate) {
        //获取筛选周期的统计数据
        QueryWrapper<AccountDayStat> wrapper = new QueryWrapper<AccountDayStat>()
                .eq("accountId", accountId)
                .between("dataDate", DateTimeUtil.getyyyyMMddByDate(startDate), DateTimeUtil.getyyyyMMddByDate(endDate))
                .eq("dataType", AccountDayStatEnum.CYCLING_INCOME.getDataType());
        List<AccountDayStat> accountDayStatList = accountDayStatDao.selectList(wrapper);
        List<String> betweenEveryDay = DateTimeUtil.getYYMMBetweenEveryDay(startDate, endDate,false);
        //获取天气
        Map<String, Accountweather> accountweatherMap = this.getWeather(accountId, startDate, endDate);
        if (CollectionUtils.isEmpty(accountDayStatList)){//
            return this.getZeroReturn(betweenEveryDay,accountweatherMap);
        }
        //存在数据，进行封装返回
        return this.getOrderFeeLineReturn(accountDayStatList,betweenEveryDay,accountweatherMap,Constants.GET_RETURN_SUM_TOTAL_TYPE);
    }

    /**
     * @description: 订单量折线图数据
     * @author: mo.shanyong
     * @date: 2025/3/7 13:51
     * @param: accountId 区域id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    @Override
    public List<OrderStatReturnDTO> getOrderNumLineData(Integer accountId, Date startDate, Date endDate) {
        //获取筛选周期的统计数据
        QueryWrapper<AccountDayStat> wrapper = new QueryWrapper<AccountDayStat>()
                .eq("accountId", accountId)
                .between("dataDate", DateTimeUtil.getyyyyMMddByDate(startDate), DateTimeUtil.getyyyyMMddByDate(endDate))
                .eq("dataType", AccountDayStatEnum.CYCLING_INCOME.getDataType());
        List<AccountDayStat> accountDayStatList = accountDayStatDao.selectList(wrapper);
        List<String> betweenEveryDay = DateTimeUtil.getYYMMBetweenEveryDay(startDate, endDate,false);
        //获取天气
        Map<String, Accountweather> accountweatherMap = this.getWeather(accountId, startDate, endDate);
        if (CollectionUtils.isEmpty(accountDayStatList)){//
            return this.getZeroReturn(betweenEveryDay,accountweatherMap);
        }
        //存在数据，进行封装返回
        return this.getOrderFeeLineReturn(accountDayStatList,betweenEveryDay,accountweatherMap,Constants.GET_RETURN_CNT_TOTAL_TYPE);
    }
    /**
     * @description: 车均收益折线图数据
     * @author: mo.shanyong
     * @date: 2025/3/7 13:51
     * @param: accountId 区域id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    @Override
    public List<OrderStatReturnDTO> getMachineAvgFeeLineData(Integer accountId, Date startDate, Date endDate) {
        //获取筛选周期的统计数据
        QueryWrapper<AccountDayStat> wrapper = new QueryWrapper<AccountDayStat>()
                .eq("accountId", accountId)
                .between("dataDate", DateTimeUtil.getyyyyMMddByDate(startDate), DateTimeUtil.getyyyyMMddByDate(endDate))
                .eq("dataType", AccountDayStatEnum.AVERAGE_VEHICLE_INCOME.getDataType());
        List<AccountDayStat> accountDayStatList = accountDayStatDao.selectList(wrapper);
        List<String> betweenEveryDay = DateTimeUtil.getYYMMBetweenEveryDay(startDate, endDate,false);
        //获取天气
        Map<String, Accountweather> accountweatherMap = this.getWeather(accountId, startDate, endDate);
        if (CollectionUtils.isEmpty(accountDayStatList)){//
            return this.getZeroReturn(betweenEveryDay,accountweatherMap);
        }
        //存在数据，进行封装返回
        return this.getOrderFeeLineReturn(accountDayStatList,betweenEveryDay,accountweatherMap,Constants.GET_RETURN_SUM_TOTAL_TYPE);
    }

    /**
     * @description: 车均单量折线图数据
     * @author: mo.shanyong
     * @date: 2025/3/7 14:56
     * @param: accountId 区域id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    @Override
    public List<OrderStatReturnDTO> getMachineAvgOrderLineData(Integer accountId, Date startDate, Date endDate) {
        //获取筛选周期的统计数据
        QueryWrapper<AccountDayStat> wrapper = new QueryWrapper<AccountDayStat>()
                .eq("accountId", accountId)
                .between("dataDate", DateTimeUtil.getyyyyMMddByDate(startDate), DateTimeUtil.getyyyyMMddByDate(endDate))
                .eq("dataType", AccountDayStatEnum.NUMBER_OF_ORDERS_PER_VEHICLE.getDataType());
        List<AccountDayStat> accountDayStatList = accountDayStatDao.selectList(wrapper);
        List<String> betweenEveryDay = DateTimeUtil.getYYMMBetweenEveryDay(startDate, endDate,false);
        //获取天气
        Map<String, Accountweather> accountweatherMap = this.getWeather(accountId, startDate, endDate);
        if (CollectionUtils.isEmpty(accountDayStatList)){//
            return this.getZeroReturn(betweenEveryDay,accountweatherMap);
        }
        //存在数据，进行封装返回
        return this.getOrderFeeLineReturn(accountDayStatList,betweenEveryDay,accountweatherMap,Constants.GET_RETURN_CNT_TOTAL_TYPE);
    }

    /**
     * @description: 正常、站外、超区订单折线图数据
     * @author: mo.shanyong
     * @date: 2025/3/7 15:03
     * @param: accountId 区域id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: com.tbit.manager.api.dto.OrderStatReturnDTO
     */
    @Override
    public List<OrderStatReturnDTO> getOrderFinishTypeData(Integer accountId, Date startDate, Date endDate) {
        return rideLogDetailsDao.getOrderFinishTypeData(accountId, startDate, endDate);
        /*//获取开始时间到结束时间包含的所有日期
        List<String> betweenEveryDay = DateTimeUtil.getYYMMBetweenEveryDay(startDate, endDate);
        //补充不存在日期的数据，补0
        return getOrderAllData(betweenEveryDay,orderFinishTypeData,"");*/

    }

    /**
     * @description: 车辆平均里程饼图数据
     * @author: mo.shanyong
     * @date: 2025/3/7 15:06
     * @param: accountId 区域id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    @Override
    public List<OrderStatReturnDTO> getOrderMileagePieData(Integer accountId, Date startDate, Date endDate) {
        List<OrderStatReturnDTO> orderMileageDataList = rideLogDetailsDao.getOrderMileageData(accountId, startDate, endDate);
        List<String> betweenEveryDay = DateTimeUtil.getYYMMBetweenEveryDay(startDate, endDate,true);
        return this.getOrderAllData(betweenEveryDay,orderMileageDataList);
    }



    /**
     * @description: 获取订单支付方式饼图数据
     * @author: mo.shanyong
     * @date: 2025/3/7 15:11
     * @param: accountId 区域id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    @Override
    public List<OrderStatReturnDTO> getOrderPayTypePieData(Integer accountId, Date startDate, Date endDate) {
        return rideLogDetailsDao.getOrderPayTypeData(accountId, startDate, endDate);
    }
    /**
     * @description: 获取时间段内区域的订单的骑行时长的分布数据
     * @author: mo.shanyong
     * @date: 2025/3/14 9:11
     * @param: accountId 区域id
     * @param: startDate 开始时间 2025-03-01 00:00:00
     * @param: endDate 结束时间 2025-03-01 23:59:59
     * @return: java.util.List<com.tbit.uqbike.object.pojo.dto.OrderMileageDTO>
     */
    @Override
    public List<OrderStatReturnDTO> getOrderTimeDistribution(Integer accountId, Date startDate, Date endDate) {
        return rideLogDetailsDao.getOrderTimeDistribution(accountId, startDate, endDate);
    }

    /**
     * @description: 获取0数据结构
     * @author: mo.shanyong
     * @date: 2025/3/7 16:30
     * @param: lastHave 上一个周期是否有统计数据
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    private Map<String, Object> getZeroData(boolean lastHave){
        Map<String, Object> dataMap = new HashMap<>();
        //订单收益
        dataMap.put(AccountDayStatEnum.CYCLING_INCOME.getFieldName(),0);
        //订单收益环比
        dataMap.put(Constants.CYCLING_INCOME_PERCENT,(lastHave ? -100 : 0) + "%");
        //订单数
        dataMap.put(Constants.CYCLING_ORDER,0);
        //订单数环比
        dataMap.put(Constants.CYCLING_ORDER_PERCENT,(lastHave ? -100 : 0) + "%");
        //车均收益
        dataMap.put(AccountDayStatEnum.AVERAGE_VEHICLE_INCOME.getFieldName(),0);
        //车均收益环比
        dataMap.put(Constants.AVERAGE_VEHICLE_INCOME_PERCENT,(lastHave ? -100 : 0) + "%");
        //车均单量
        dataMap.put(AccountDayStatEnum.NUMBER_OF_ORDERS_PER_VEHICLE.getFieldName(),0);
        //车均单量环比
        dataMap.put(Constants.NUMBER_OF_ORDERS_PER_VEHICLE_PERCENT,(lastHave ? -100 : 0) + "%");
        //单均时长
        dataMap.put(AccountDayStatEnum.MACHINE_RIDING_TIME.getFieldName(),0);
        //单均时长环比
        dataMap.put(Constants.MACHINE_RIDING_TIME_PERCENT,(lastHave ? -100 : 0) + "%");
        //单均里程
        dataMap.put(AccountDayStatEnum.ACCUMULATED_MILEAGE.getFieldName(),0);
        //单均里程环比
        dataMap.put(Constants.ACCUMULATED_MILEAGE_PERCENT,(lastHave ? -100 : 0) + "%");
        return dataMap;
    }

    /**
     * @description: 获取筛选周期的上一个周期的统计数据
     * @author: mo.shanyong
     * @date: 2025/3/7 16:39
     * @param: accountId
     * @param: startDate
     * @param: endDate
     * @return: java.util.List<com.tbit.uqbike.object.pojo.AccountDayStat>
     */
    private List<AccountDayStat> getLastCycleStat(Integer accountId,Date startDate,Date endDate){
        // 获取当前周期的时间范围
        LocalDate currentStartDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate currentEndDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

        // 获取上个周期的时间范围
        LocalDate lastStartDate = currentStartDate.minusDays(currentEndDate.toEpochDay() - currentStartDate.toEpochDay() + 1);
        LocalDate lastEndDate = currentEndDate.minusDays(currentEndDate.toEpochDay() - currentStartDate.toEpochDay() + 1);
        Integer from = DateTimeUtil.getyyyyMMddByLocateDate(lastStartDate);
        Integer to = DateTimeUtil.getyyyyMMddByLocateDate(lastEndDate);
        QueryWrapper<AccountDayStat> wrapper = new QueryWrapper<AccountDayStat>()
                .eq("accountId", accountId)
                .between("dataDate",from , to)
                .in("dataType", AccountDayStatEnum.getOrderAnalysisDataType());
        return accountDayStatDao.selectList(wrapper);
    }

    /**
     * @description: 获取计算订单的核心数据
     * @author: mo.shanyong
     * @date: 2025/3/7 16:52
     * @param: accountDayStatMap
     * @param: lastAccountDayStatMap
     * @return: java.util.Map<java.lang.String, java.lang.Object>
     */
    private Map<String,Object> getBaseData(Map<Integer, List<AccountDayStat>> accountDayStatMap,Map<Integer, List<AccountDayStat>> lastAccountDayStatMap){
        List<Integer> orderAnalysisDataType = AccountDayStatEnum.getOrderAnalysisDataType();
        //先获取O数据
        Map<String, Object> dataMap = this.getZeroData(false);
        //获取订单分析核心数据类型
        for (Integer dateType : orderAnalysisDataType) {
            List<AccountDayStat> accountDayStatList = accountDayStatMap.computeIfAbsent(dateType, k -> new ArrayList<>());
            List<AccountDayStat> lastAccountDayStatList = lastAccountDayStatMap.computeIfAbsent(dateType, k -> new ArrayList<>());
            switch (dateType){
                case AccountDayStatConstant.CYCLING_INCOME://订单收益
                    //订单收益
                    this.sumSumTotal(AccountDayStatEnum.CYCLING_INCOME.getFieldName(),Constants.CYCLING_INCOME_PERCENT,accountDayStatList,lastAccountDayStatList,dataMap);
                    //订单量
                    this.sumCntTotal(Constants.CYCLING_ORDER,Constants.CYCLING_ORDER_PERCENT,accountDayStatList,lastAccountDayStatList,dataMap);
                    break;
                case AccountDayStatConstant.AVERAGE_VEHICLE_INCOME://车均收益
                    this.sumSumTotalAgv(AccountDayStatEnum.AVERAGE_VEHICLE_INCOME.getFieldName(),Constants.AVERAGE_VEHICLE_INCOME_PERCENT,accountDayStatList,lastAccountDayStatList,dataMap);
                    break;
                case AccountDayStatConstant.NUMBER_OF_ORDERS_PER_VEHICLE://车均单量
                    this.sumCntTotalAgv(AccountDayStatEnum.NUMBER_OF_ORDERS_PER_VEHICLE.getFieldName(),Constants.NUMBER_OF_ORDERS_PER_VEHICLE_PERCENT,accountDayStatList,lastAccountDayStatList,dataMap);
                    break;
                case AccountDayStatConstant.MACHINE_RIDING_TIME://单均时长
                    this.getMinuteAvg(accountDayStatMap,lastAccountDayStatMap,dataMap);
                    break;
                case AccountDayStatConstant.ACCUMULATED_MILEAGE://单均里程
                    this.getAvgMileage(accountDayStatMap,lastAccountDayStatMap,dataMap);
                    break;
            }
        }
        return dataMap;
    }

    /**
     * @description: 求金额的总和，并计算环比
     * @author: mo.shanyong
     * @date: 2025/3/12 10:19
     * @param: name
     * @param: percentName
     * @param: accountDayStatList
     * @param: lastAccountDayStatList
     * @param: dataMap
     */
    private void sumSumTotal(String name,String percentName,List<AccountDayStat> accountDayStatList,List<AccountDayStat> lastAccountDayStatList,Map<String, Object> dataMap){
        long sum = accountDayStatList.stream().mapToLong(AccountDayStat::getSumTotal).sum();
        dataMap.put(name, NumberUtil.div(sum, 100, 2));
        long lastSum = lastAccountDayStatList.stream().mapToLong(AccountDayStat::getSumTotal).sum();
        double percent = 0d;
        if (lastSum != 0L) {
            percent = NumberUtil.div((sum - lastSum), lastSum, 4);
        }
        percent = percent == 0d && sum != 0 && sum != lastSum ? 1 : percent;
        dataMap.put(percentName,NumberUtil.mul(percent,100) + "%");
    }

    /**
     * @description: 求金额总和求平均，并计算环比
     * @author: mo.shanyong
     * @date: 2025/3/12 10:20
     * @param: name
     * @param: percentName
     * @param: accountDayStatList
     * @param: lastAccountDayStatList
     * @param: dataMap
     */
    private void sumSumTotalAgv(String name,String percentName,List<AccountDayStat> accountDayStatList,List<AccountDayStat> lastAccountDayStatList,Map<String, Object> dataMap){
        long sum = accountDayStatList.stream().mapToLong(AccountDayStat::getSumTotal).sum();
        double sumTotal = NumberUtil.div(sum, 100, 2);
        double sumTotalAgv = !accountDayStatList.isEmpty() ? NumberUtil.div(sumTotal,accountDayStatList.size(),2) : 0;
        dataMap.put(name, sumTotalAgv);

        long lastSum = lastAccountDayStatList.stream().mapToLong(AccountDayStat::getSumTotal).sum();
        double lastSumTotal = NumberUtil.div(lastSum, 100, 2);
        double lastSumTotalAgv = !lastAccountDayStatList.isEmpty() ? NumberUtil.div(lastSumTotal,lastAccountDayStatList.size(),2) : 0;
        double percent = 0d;
        if (lastSumTotalAgv != 0d) {
            percent = NumberUtil.div((sumTotalAgv - lastSumTotalAgv), lastSumTotalAgv, 4);
        }
        percent = percent == 0d && sum != 0 && sum != lastSum ? 1 : percent;
        dataMap.put(percentName,NumberUtil.mul(percent,100) + "%");
    }

    /**
     * @description: 求数量的总和，并计算环比
     * @author: mo.shanyong
     * @date: 2025/3/12 10:19
     * @param: name
     * @param: percentName
     * @param: accountDayStatList
     * @param: lastAccountDayStatList
     * @param: dataMap
     */
    private void sumCntTotal(String name,String percentName,List<AccountDayStat> accountDayStatList,List<AccountDayStat> lastAccountDayStatList,Map<String, Object> dataMap){
        long cntTotal = accountDayStatList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        dataMap.put(name,cntTotal);
        long lastCntTotal = lastAccountDayStatList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        double cntPercent = 0d;
        if (lastCntTotal != 0L) {
            cntPercent = NumberUtil.div((cntTotal - lastCntTotal), lastCntTotal, 4);
        }
        cntPercent = cntPercent == 0d && cntTotal != 0 && cntTotal != lastCntTotal ? 1 : cntPercent;
        dataMap.put(percentName,NumberUtil.mul(cntPercent,100) + "%");
    }

    /**
     * @description: 求数量的总和求平均，并计算环比
     * @author: mo.shanyong
     * @date: 2025/3/12 10:19
     * @param: name
     * @param: percentName
     * @param: accountDayStatList
     * @param: lastAccountDayStatList
     * @param: dataMap
     */
    private void sumCntTotalAgv(String name,String percentName,List<AccountDayStat> accountDayStatList,List<AccountDayStat> lastAccountDayStatList,Map<String, Object> dataMap){
        long cntTotal = accountDayStatList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        double ordersPerVehicle = !accountDayStatList.isEmpty() ? NumberUtil.div(cntTotal, accountDayStatList.size() * 100, 2) : 0;
        dataMap.put(name,ordersPerVehicle);
        long lastCntTotal = lastAccountDayStatList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        double lastOrdersPerVehicle = !lastAccountDayStatList.isEmpty() ? NumberUtil.div(lastCntTotal, lastAccountDayStatList.size() * 100, 2) : 0;
        double cntPercent = 0d;
        if (lastOrdersPerVehicle != 0d) {
            cntPercent = NumberUtil.div((ordersPerVehicle - lastOrdersPerVehicle), lastOrdersPerVehicle, 4);
        }
        cntPercent = cntPercent == 0d && cntTotal != 0 && cntTotal != lastCntTotal ? 1 : cntPercent;
        dataMap.put(percentName,NumberUtil.mul(cntPercent,100) + "%");
    }

    /**
     * 车均骑行里程 订单总里程/订单数
     */
    private void getAvgMileage(Map<Integer, List<AccountDayStat>> accountDayStatMap,Map<Integer, List<AccountDayStat>> lastAccountDayStatMap,Map<String, Object> dataMap){
        List<AccountDayStat> accountDayStatOrderList = accountDayStatMap.computeIfAbsent(AccountDayStatEnum.CYCLING_INCOME.getDataType(),k->new ArrayList<>());
        List<AccountDayStat> lastAccountDayStatOrderList = lastAccountDayStatMap.computeIfAbsent(AccountDayStatEnum.CYCLING_INCOME.getDataType(),k->new ArrayList<>());
        List<AccountDayStat> accountDayStatMileageList = accountDayStatMap.computeIfAbsent(AccountDayStatEnum.ACCUMULATED_MILEAGE.getDataType(),k->new ArrayList<>());
        List<AccountDayStat> lastAccountDayStatMileageList = lastAccountDayStatMap.computeIfAbsent(AccountDayStatEnum.ACCUMULATED_MILEAGE.getDataType(),k->new ArrayList<>());

        /**
         * 当前周期的总订单数、总骑行里程
         * */
        long orderCount = accountDayStatOrderList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        long mileage = accountDayStatMileageList.stream().mapToLong(AccountDayStat::getSumTotal).sum();

        /**
         * 上一个周期的总订单数、总骑行里程
         * */
        long lastOrderCount = lastAccountDayStatOrderList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        long lastMileage = lastAccountDayStatMileageList.stream().mapToLong(AccountDayStat::getSumTotal).sum();

        double nowAvgMileage = orderCount == 0L ? 0L : NumberUtil.div(mileage, orderCount * 1000, 2);
        double lastAvgMileage = lastOrderCount == 0L ? 0L : NumberUtil.div(lastMileage, lastOrderCount * 1000, 2);
        dataMap.put(AccountDayStatEnum.ACCUMULATED_MILEAGE.getFieldName(),nowAvgMileage);

        double avgMileagePercent = lastAvgMileage == 0L ? 0L : NumberUtil.div((nowAvgMileage - lastAvgMileage), lastAvgMileage, 4);
        dataMap.put(Constants.ACCUMULATED_MILEAGE_PERCENT,(lastAvgMileage == 0L && nowAvgMileage != 0L ? 100 : NumberUtil.mul(avgMileagePercent,100)) + "%");
    }

    /**
     * 计算车均骑行时长 总骑行时长/订单数
     * @return string
     */
    private void getMinuteAvg(Map<Integer, List<AccountDayStat>> accountDayStatMap,Map<Integer, List<AccountDayStat>> lastAccountDayStatMap,Map<String, Object> dataMap){
        List<AccountDayStat> accountDayStatOrderList = accountDayStatMap.computeIfAbsent(AccountDayStatEnum.CYCLING_INCOME.getDataType(),k -> new ArrayList<>());
        List<AccountDayStat> lastAccountDayStatOrderList = lastAccountDayStatMap.computeIfAbsent(AccountDayStatEnum.CYCLING_INCOME.getDataType(),k -> new ArrayList<>());
        List<AccountDayStat> accountDayStatRideTimeList = accountDayStatMap.computeIfAbsent(AccountDayStatEnum.MACHINE_RIDING_TIME.getDataType(),k -> new ArrayList<>());
        List<AccountDayStat> lastAccountDayStatRideTimeList = lastAccountDayStatMap.computeIfAbsent(AccountDayStatEnum.MACHINE_RIDING_TIME.getDataType(),k -> new ArrayList<>());

        /**
         * 当前周期的总订单数、总骑行时长
         * */
        long orderCount = accountDayStatOrderList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        long rideTime = accountDayStatRideTimeList.stream().mapToLong(AccountDayStat::getSumTotal).sum();

        /**
         * 上一个周期的总订单数、总骑行时长
         * */
        long lastOrderCount = lastAccountDayStatOrderList.stream().mapToLong(AccountDayStat::getCntTotal).sum();
        long lastRideTime = lastAccountDayStatRideTimeList.stream().mapToLong(AccountDayStat::getSumTotal).sum();

        double nowAvgRideTime = orderCount == 0L ? 0L : NumberUtil.div(rideTime, orderCount * 60, 2);
        double lastAvgRideTime = lastOrderCount == 0L ? 0L : NumberUtil.div(lastRideTime, lastOrderCount * 60, 2);
        dataMap.put(AccountDayStatEnum.MACHINE_RIDING_TIME.getFieldName(),nowAvgRideTime);


        double avgRideTimePercent = lastAvgRideTime == 0L ? 0L : NumberUtil.div((nowAvgRideTime - lastAvgRideTime), lastAvgRideTime, 4);
        dataMap.put(Constants.MACHINE_RIDING_TIME_PERCENT,(lastAvgRideTime == 0L && nowAvgRideTime != 0L ? 100 : NumberUtil.mul(avgRideTimePercent,100)) + "%");
    }
    /**
     * @description: 获取时间段的天气情况
     * @author: mo.shanyong
     * @date: 2025/3/10 11:47
     * @param: accountId 区域Id
     * @param: startDate 开始时间
     * @param: endDate 结束时间
     * @return: java.util.Map<java.lang.String, com.tbit.uqbike.object.pojo.Accountweather>
     */
    private Map<String,Accountweather> getWeather(Integer accountId,Date startDate,Date endDate){
        List<Accountweather> accountweathers = accountweatherDao.queryAllByLimit(accountId, startDate, endDate);
        if (CollectionUtils.isEmpty(accountweathers)){
            return new HashMap<>();
        }
        return accountweathers.stream().collect(Collectors.toMap(Accountweather::getDate, Function.identity()));
    }
    /**
     * @description: 获取空数据
     * @author: mo.shanyong
     * @date: 2025/3/10 11:52
     * @param: betweenEveryDay 间隔日期
     * @param: accountweatherMap 天气
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    private List<OrderStatReturnDTO> getZeroReturn(List<String> betweenEveryDay,Map<String, Accountweather> accountweatherMap){
        List<OrderStatReturnDTO> orderStatReturnList = new ArrayList<>();
        for (String day : betweenEveryDay) {
            Accountweather accountweather = accountweatherMap.computeIfAbsent(day,k->new Accountweather());
            OrderStatReturnDTO orderStatReturn = new OrderStatReturnDTO();
            orderStatReturn.setKeyData(day);
            orderStatReturn.setTempMax(accountweather.getTempMax());
            orderStatReturn.setIconDay(WeatherEnum.getNameByCode(accountweather.getIconDay()));
            orderStatReturn.setValue(0);
            orderStatReturnList.add(orderStatReturn);
        }
        return orderStatReturnList;
    }

    /**
     * @description: 封装返回数据
     * @author: mo.shanyong
     * @date: 2025/3/10 13:34
     * @param: accountDayStatList 数据
     * @param: betweenEveryDay 间隔日期
     * @param: accountweatherMap 天气
     * @param: accountweatherMap 0-sumTotal;1-cntTotal
     * @return: java.util.List<com.tbit.manager.api.dto.OrderStatReturnDTO>
     */
    private List<OrderStatReturnDTO> getOrderFeeLineReturn(List<AccountDayStat> accountDayStatList,List<String> betweenEveryDay,
                                                        Map<String, Accountweather> accountweatherMap,Integer type){
        Map<String, AccountDayStat> accountDayStatMap = accountDayStatList.stream().collect(Collectors.toMap(accountDayStat -> {
            return DateTimeUtil.getMMDDByDate(accountDayStat.getDataDate());
        }, Function.identity()));
        List<OrderStatReturnDTO> orderStatReturnList = new ArrayList<>();
        for (String day : betweenEveryDay) {
            AccountDayStat accountDayStat = accountDayStatMap.get(day);
            Accountweather accountweather = accountweatherMap.computeIfAbsent(day,k->new Accountweather());
            OrderStatReturnDTO orderStatReturn = new OrderStatReturnDTO();
            orderStatReturn.setKeyData(day);
            orderStatReturn.setTempMax(accountweather.getTempMax());
            orderStatReturn.setIconDay(WeatherEnum.getNameByCode(accountweather.getIconDay()));
            orderStatReturn.setValue(Objects.nonNull(accountDayStat) ? (Objects.equals(type,Constants.GET_RETURN_CNT_TOTAL_TYPE) ? accountDayStat.getCntTotal() : NumberUtil.div(accountDayStat.getSumTotal(),100,2)) : 0);
            orderStatReturnList.add(orderStatReturn);
        }
        return orderStatReturnList;
    }

    /**
     * @description: 检查查询的时间段内不存在的数据的日期，补充，返回0
     * @author: mo.shanyong
     * @date: 2025/3/10 20:05
     * @param: keyDataList
     * @param: orderStatReturnList 查询到的数据
     * @return: java.util.List<com.tbit.uqbike.object.pojo.statistics.OrderStatPieReturn>
     */
    private List<OrderStatReturnDTO> getOrderAllData(List<String> keyDataList,
                                                            List<OrderStatReturnDTO> orderStatReturnList){
        if (CollectionUtils.isEmpty(orderStatReturnList)){
            List<OrderStatReturnDTO> orderStatReturnDTOS = getZeroReturn(keyDataList, new HashMap<>());
            orderStatReturnDTOS.forEach(orderStatReturnDTO -> {
                String keyData = orderStatReturnDTO.getKeyData();
                String[] split = keyData.split("年");
                orderStatReturnDTO.setKeyData(StringUtils.startsWith(split[1],"0") ? split[1].replaceFirst("0","") : split[1]);
            });
            return orderStatReturnDTOS;
        }
        Map<String, OrderStatReturnDTO> orderStatReturnMap = orderStatReturnList.stream().collect(Collectors.toMap(OrderStatReturnDTO::getKeyData, Function.identity()));
        for (String keyData : keyDataList) {
            OrderStatReturnDTO orderStatReturn = orderStatReturnMap.get(keyData);
            if (Objects.isNull(orderStatReturn)){//不存在的区间段要补0
                OrderStatReturnDTO statReturn = new OrderStatReturnDTO();
                statReturn.setKeyData(keyData);
                statReturn.setValue(0);
                orderStatReturnList.add(statReturn);
            }
        }
        //排序
        orderStatReturnList = orderStatReturnList.stream().sorted(Comparator.comparing(orderStatReturnDTO -> {
            String keyData = orderStatReturnDTO.getKeyData();
            return Integer.parseInt(keyData.replace("年","").replace("月","").replace("日",""));
        })).collect(Collectors.toList());

        orderStatReturnList.forEach(orderStatReturnDTO -> {
            String keyData = orderStatReturnDTO.getKeyData();
            String[] split = keyData.split("年");
            orderStatReturnDTO.setKeyData(StringUtils.startsWith(split[1],"0") ? split[1].replaceFirst("0","") : split[1]);
        });
        return orderStatReturnList;
    }
}
